package com.nsyue.auth.controller.verify;

import cn.hutool.json.JSONUtil;
import com.nsyue.auth.controller.result.ApiStatusEnum;
import com.nsyue.auth.entity.ThirdSystem;
import com.nsyue.auth.exception.NsyueAuthException;
import com.nsyue.auth.service.ThirdSystemService;
import com.nsyue.auth.utils.CryptoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.TreeMap;


/**
 * 接口验签
 */
@Slf4j
@ControllerAdvice
public class VerifySignRequest extends RequestBodyAdviceAdapter {

    @Autowired
    private ThirdSystemService thirdSystemService;

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(VerifySign.class) || methodParameter.hasParameterAnnotation(VerifySign.class);
    }
 
    @Override
    public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        byte[] body = new byte[inputMessage.getBody().available()];
        int read = inputMessage.getBody().read(body);
        String json = new String(body);
        verify(json);
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new HttpInputMessage() {
            @Override
            public InputStream getBody() throws IOException {
                return bais;
            }
            @Override
            public HttpHeaders getHeaders() {
                return inputMessage.getHeaders();
            }
        };
    }

    private void verify(String json) {
        boolean isVerified = false;
        try {
            TreeMap treeMap = JSONUtil.toBean(json, TreeMap.class);
            String signature = (String) treeMap.remove("sign");
            String appid = (String) treeMap.get("appid");
            StringBuffer buffer = new StringBuffer(appid);
            for (Object key : treeMap.keySet()) {
                Object value = treeMap.get(key);
                buffer.append(key).append(value);
            }
            buffer.append(appid);

            ThirdSystem thirdSystem = thirdSystemService.getPublicKeyByAppid(appid);
            String publicKey = thirdSystem.getPublicKey();
            /*----test----*/
            String testSign = CryptoUtils.signBySHA256WithRSA(thirdSystem.getPrivateKey(), buffer.toString());
            System.out.println(testSign);
            /*----test end----*/
            // 验签，成功 isVerified=true
            isVerified = CryptoUtils.verifyBySHA256WithRSA(publicKey, buffer.toString(), signature);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        if (!isVerified) {
            throw new NsyueAuthException(ApiStatusEnum.INVALID_SIGNATURE);
        }
    }
}